Devcontainerを用いてPythonやAWS CDK・Serverless Frameworkなどのデプロイ環境の構築をしてみた

Devcontainerを用いてPythonやAWS CDK・Serverless Frameworkなどのデプロイ環境の構築をしてみた

Clock Icon2024.07.29

データアナリティクス事業本部のueharaです。

今回は、Devcontainerを用いてPythonやAWS CDK・Serverless Frameworkなどのデプロイ環境の構築をしてみたいと思います。

Devcontainerとは

Devcontainerは一言でいうとVSCodeの開発環境構築支援機能になります。

Dockerコンテナを開発環境として利用することで、開発やデプロイに必要なランタイムのバージョンやライブラリ、VSCodeの拡張機能をコンテナ内に包含させることができます。

ユーザはプロジェクトディレクトリを開く際にDevcontainerで起動をするだけで開発環境が準備されるので、案件に新しくアサインされるメンバーもすぐに開発・デプロイをすることができます。

20240729_devcontainer_00
(引用元)

今回作成する環境

今回は、私が普段案件に参画する際によく使う以下のランタイムやライブラリを含むDevcontainerを作成したいと思います。

  • Python
  • Node.js
  • AWS CDK
  • AWS SAM
  • Serverless Framework

事前準備

VSCodeのインストールと、Devcontainerの拡張機能をインストールしておきます。

20240729_devcontainer_01

やってみた

ディレクトリ構成

まず、ディレクトリ構成ですが、今回はシンプルに以下のようにしてみました。

$ tree . -a
.
├── .devcontainer.json
├── Dockerfile
└── src
    └── test.py

各ファイルの記述

早速ですが、 Dockerfile は以下のように書いてみました。

Dockerfile
# syntax=docker/dockerfile:1
FROM debian:bookworm-slim

# バージョンの指定
ARG PYTHON_VERSION=3.11
ARG NODEJS_VERSION=20.16.0
ARG AWS_CDK_VERSION=2.150.0
ARG SERVERLESS_VERSION=3.38.0
ARG AWS_SAM_VERSION=1.120.0

# ターゲットのアーキテクチャ
ARG TARGETARCH

# 環境変数の設定
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH="/root/.local/bin:${PATH}"

# APTキャッシュの設定
RUN rm -f /etc/apt/apt.conf.d/docker-clean; \
    echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache

# 基本的なシステムパッケージのインストール
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt,sharing=locked \
    apt-get update && apt-get install --no-install-recommends -y \
    curl \
    gnupg \
    lsb-release \
    software-properties-common \
    bash \
    jq \
    unzip \
    git

# Pythonのインストール
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt,sharing=locked \
    apt-get update && apt-get install --no-install-recommends -y \
    python${PYTHON_VERSION} \
    python3-pip \
    python3-venv \
    && python3 -m venv /opt/venv

# 仮想環境を有効化
ENV PATH="/opt/venv/bin:$PATH"

# Node.jsのインストール
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt,sharing=locked \
    curl -fsSL https://deb.nodesource.com/setup_${NODEJS_VERSION%%.*}.x | bash - \
    && apt-get update \
    && apt-get install --no-install-recommends -y nodejs=${NODEJS_VERSION}-1nodesource1 \
    && npm install -g npm@latest

# AWS CLIのインストール
RUN case ${TARGETARCH} in \
        "amd64") \
            AWS_CLI_URL="https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" ;; \
        "arm64") \
            AWS_CLI_URL="https://awscli.amazonaws.com/awscli-exe-linux-aarch64.zip" ;; \
        *) \
            echo "Unsupported architecture: ${TARGETARCH}" >&2; \
            exit 1 ;; \
    esac && \
    curl "${AWS_CLI_URL}" -o "awscliv2.zip" && \
    unzip awscliv2.zip && \
    ./aws/install && \
    rm -rf aws awscliv2.zip

# AWS CDK, Typescript, AWS SAM, Serverless Frameworkのインストール
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
    --mount=type=cache,target=/root/.cache/pip,sharing=locked \
    npm install -g typescript aws-cdk@${AWS_CDK_VERSION} serverless@${SERVERLESS_VERSION} \
    && pip3 install aws-sam-cli==${AWS_SAM_VERSION}

# 作業ディレクトリの設定
WORKDIR /workspace

# デフォルトのシェルをbashに設定
SHELL ["/bin/bash", "-c"]

# コンテナ起動時のデフォルトコマンド
CMD ["/bin/bash"]

ベースイメージはDebian Boockwormで、特に使用頻度の低いパッケージを除いたslim版を利用しています。

ランタイムやライブラリのバージョンは以下のように ARG を用いて定義しています。

ARG PYTHON_VERSION=3.11
ARG NODEJS_VERSION=20.16.0
ARG AWS_CDK_VERSION=2.150.0
ARG SERVERLESS_VERSION=3.38.0
ARG AWS_SAM_VERSION=1.120.0

今回は開発環境の構築のためマルチステージビルドは利用していません。

apt-getpip の実行時には RUN --mount=type=cache というキャッシュディレクトリを指定する機能を利用しています。(Docker 18.09より統合されたBuildKitが必要になります)

指定されたディレクトリはビルドを跨いでデータを保持しておくことができ、かつディレクトリ内のファイルはレイヤーに含まれなくなりますので、イメージサイズが小さくなるというメリットがあります。

例えば apt-get コマンドの実行時にはこれまではお作法的に apt-get cleanrm -rf /var/lib/apt/lists/* を実行してイメージサイズを小さくしていたと思いますが、上記の通り RUN --mount=type=cache をするとレイヤーに含まれなくなるのでそれが不要になります。
※むしろ、キャッシュとしてビルドを跨いで利用したいので、 Dockerfile 内に以下の通りapt操作後に自動的にクリーンアップが実行されるのを防ぐ記載をしています。

# APTキャッシュの設定
RUN rm -f /etc/apt/apt.conf.d/docker-clean; \
    echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache

次に、.devcontainer.json は以下の通りです。

.devcontainer.json
{
    "name": "My DevContainer", 
    "build": {
        "dockerfile": "Dockerfile"
    },
    "workspaceFolder": "/workspace", 
    "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
    "mounts": [
        // AWSのプロファイルディレクトリをマウント
        "source=${localEnv:HOME}/.aws,target=/root/.aws,type=bind,consistency=cached"
    ]
}

ビルドは先に作成した Dockerfile を参照するようにしています。

ワークスペースのディレクトリはそのまま /workspace です。

mounts については、いまいまはAWSの認証情報のみを指定しています。

例えば npm install を使用して node_modules などマウントする必要のないファイルやディレクトリができる場合は名前付きボリュームで指定しておいた方が良いかと思いますが、ここでは省略しています。

test.py は単に実行確認のため、以下にしています。

test.py
print("Hello World!")

Devcontainerの起動

作成したディレクトリをVSCodeで開きます。

すると、以下のように右下にコンテナで開くことをサジェストするポップアップが表示されます。

20240729_devcontainer_02

ここから起動しても良いのですが、コマンドパレットで Rebuild and Reopen in Container を指定してビルドとコンテナの起動を実行してみます。

20240729_devcontainer_03

コンテナのビルドが完了すると、コンテナに接続されたVSCode(実際にはコンテナ内にもVSCodeが存在)が起動します。

20240729_devcontainer_04

冒頭で述べた通り拡張機能もローカルのVSCodeからは分離されているのですが、以下の図のボタンから一括でローカルの拡張機能をインストールすることもできます。

20240729_devcontainer_05

実行確認

Devcontainerが起動できたので、ランタイムやライブラリが期待通りにインストールされているか、ターミナルのタブからコマンドを叩いて確認してみます。

20240729_devcontainer_06

期待通りインストールできていることが確認できました。

test.py もテストのため実行してみます。

20240729_devcontainer_07

こちらも問題なく実行できました。

最後に

今回は、Devcontainerを用いてPythonやAWS CDK・Serverless Frameworkなどのデプロイ環境の構築をしてみました。

参考になりましたら幸いです。

参考文献

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.